package org.ejde.periscope;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.UIManager;

import org.ejde.sciencelogs.UdpXmitter;
import org.ejde.sciencelogs.fieldFactory;
import org.ejde.sciencelogs.iniParser;
import org.ejde.sciencelogs.mainPanel;
import org.ejde.sciencelogs.smackClient;

/**
 * For use in annotation data collection from multiple users contributing to a
 * single operation. These annotations can help provide a context for the other
 * data collected on expeditions ranging from exploration to science, and help
 * provide a consistent set of vocabulary despite a diverse number of
 * contributors with varied specialties.
 * 
 * Originally developed for use by the Institute for Exploration (IFE), other
 * groups are expected to use this sort of freely configurable GUI for use in a
 * variety of applications.
 * 
 * @author Eric Martin
 * @version 0.1
 */
public class Periscope extends JFrame {

	/**
	 * Auto-generated serialVersionUID
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * mainPanel object for the Periscope class
	 */
	public mainPanel mp;

	/**
	 * Constructor method for the Periscope class. Creates the main window for
	 * the project. Does not handle the creation of the login window.
	 * 
	 * @param ini
	 *            configuration file object
	 * @param ff
	 *            fieldfactory object for creating the XML-driven, run-time UI
	 * @param udp
	 *            UDP network client object (for non-XMPP logging)
	 * @param smack
	 *            XMPP client object (for XMPP logging)
	 */
	public Periscope(iniParser ini, fieldFactory ff, UdpXmitter udp,
			smackClient smack) {
		super(ini.Title);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
		}
		// this.setSize(600,400);
		// ff.setParentFrame(this);

		mp = new mainPanel(ini, ff, udp, smack);

		setContentPane(mp);
		
		// Set the Periscope frame as the parent frame to
		// the fieldFactory object.
		ff.setParentFrame(this);

	}

	/**
	 * Method to compact the UI sub-panels.
	 */
	public void packsubpanels() {
		// Added to pack up desired subpanels
		for (int n = 0; n < mp.tp.tabs.length; n++) {
			for (int m = 0; m < mp.tp.tabs[n].subpanels.length; m++) {
				mp.tp.tabs[n].subpanels[m].shrinkInit();
			}
		}

	}

	/**
	 * Main function for the Periscope project.
	 * 
	 * @param args
	 *            command-line arguments, an XML configuration file
	 * @throws IOException
	 */
	public static void main(String args[]) throws IOException {

		// Main frame for Periscope
		Periscope frame;

		// Configuration information
		iniParser ini;

		// Run-time generated UI Objects
		fieldFactory ff;

		// Non-XMPP-based logging
		UdpXmitter udp;

		// XMPP-based logging
		smackClient smack = null;

		//
		BufferedWriter logwriter = null;

		// Logfile name
		String fname = null;

		// Default XML configuration file.
		String xmlfile = "http://localhost/periscope/interface.xml";

		// Look to see if there is a command-line argument.
		// If there is one, set it as the XML configuration
		// file.
		if (args.length == 1) {

			// TODO
			// Need to verify argument is a valid file.
			xmlfile = args[0];
		}

		// Parse XML configuration file, create parsed
		// object.
		ini = new iniParser(xmlfile);

		// Use parsed object to build array of UI elements.
		ff = new fieldFactory(ini);

		// Test if we should be writing to a local file.
		if (ini.getLocalLog() == 1) {

			// Get the name of the local logfile from the
			// configuration file
			int overwrite = 1;
			File logfile = new File(ini.getLocalLogFile());

			// Test to see if the specified logfile already
			// exists.
			if (logfile.exists()) {

				// If the local logfile exists, new events
				// will be appended to it.
				JOptionPane.showMessageDialog(null,
						"The file: " + logfile.getName() + " already exists. "
								+ "Scilog will append it. I know your fear.",
						"Log File Exists", JOptionPane.INFORMATION_MESSAGE);

				overwrite = 0;
			}

			// Open the local logfile object
			if (overwrite == 1) {
				// Code for a new local logfile
				try {
					logwriter = new BufferedWriter(new FileWriter(
							logfile.getAbsoluteFile()));
					fname = logfile.getAbsolutePath();
					logwriter.close();
				} catch (IOException e) {
					e.printStackTrace();
					fname = null;
				}

			} else if (overwrite == 0) {
				// Code to append to an existing logfile
				try {
					logwriter = new BufferedWriter(new FileWriter(
							logfile.getAbsoluteFile(), true));
					fname = logfile.getAbsolutePath();
					logwriter.close();
				} catch (IOException e) {
					e.printStackTrace();
					fname = null;
				}
			}
		}

		// Setup the UDP-based logging.
		if (fname == null) {
			// Code if there is no local logfile
			udp = new UdpXmitter(ini.getDestIP(), ini.getDestPort());
		} else {
			// Code if there is a local logfile
			udp = new UdpXmitter(ini.getDestIP(), ini.getDestPort(), fname,
					ini.getLoggerDelimiter());
		}

		// Setup XMPP-based logging
		if (ini.getXmppEnabled() == 1) {

			/* XMPP connection */
			// Enable the XMPP Debugger
			// XMPPConnection.DEBUG_ENABLED = false;

			// Setup the XMPP client
			smack = new smackClient(ini.getXmppServer(),
					ini.getXmppServerPort(), false);

			// Attempt to Login to XMPP Server
			if (!smack.loginWindow()) {
				// If login fails; Exit program
				JOptionPane.showMessageDialog(null,
						"Cannot Login: bad login or server not found.",
						"Server Error", JOptionPane.ERROR_MESSAGE);
				System.exit(ERROR);
			} else {
				// If login successful; Attempt to join the MUC
				if (!smack.joinMUC(ini.getXmppTargetRoom())) {
					System.err.println();
					JOptionPane
							.showMessageDialog(null, "Cannot Join chat room: "
									+ ini.getXmppTargetRoom(), "Server Error",
									JOptionPane.ERROR_MESSAGE);
				}
				// TODO
				// Add code to handle when XMPP login is
				// successful but MUC connection fails
			}
		}

		// Create main window
		frame = new Periscope(ini, ff, udp, smack);

		// Main window actions
		frame.pack();
		frame.packsubpanels();
		frame.setVisible(true);
		frame.setResizable(false);
	}
}
